iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 17
0

SQL很慢怎麼辦?

遇到這情況通常都是兩個原因

  • SQL的語法有問題,沒有使用到MySQL的索引
  • 資料量真的太多,幾千萬上億筆

第一種情況好解,把慢的SQL語法都整理一下,使用索引就可以!
EX:
SELECT * FROM table1 WHERE order_time BETWEEN 1600852500 AND 1601842200

這時候可以對order_time這欄位加一個index

CREATE INDEX order_time
ON `table1` (`order_time`);

這一句SQL的查詢速度會大大提升,本來要花10秒,現在可能不到1秒就跑出來。這是你加CPU & RAM也不會達到的效果!

那全部的欄位都加上索引不就世界和平嗎??
不~索引愈多insert要花的時間愈久,所以要取一個平衝點,把全部的SQL都整理起來,找出共同的條件,再建立索引,盡可能讓使用頻率高的語法都吃到索引。

BUT終有一天這語法還是有可能會慢,那就是資料太多了

  1. 這時候可以考慮做冷熱的資料分表,把最近的資料放一起(熱表),比較久的資料放一起(冷表),通常愈近的資料愈常被搜尋到,放在資料比較少的熱表,查詢速度會加快。
  2. 表做水平分割,例如說資料可以分國家、地區或者特殊的演算法來拆表,透過把資料的量分散到不同的表,加快查詢速度。
  3. 砍資料!可以建partition,再用排程去定期砍資料,保持表的資料量不會太大,畢竟不是全部的資料都值得保留。

來建index吧~

把SQL列出來

table: tasks

SELECT * FROM `tasks` WHERE user_id = "102968676886378479010" AND parent_id in (1) AND status IN (1) ORDER BY created_timestamp ASC
SELECT * FROM `tasks` WHERE user_id = "102968676886378479010" AND parent_id = 0 AND status = 1 ORDER BY created_timestamp ASC
SELECT id, parent_id, name, created_timestamp FROM `tasks` WHERE user_id = "102968676886378479010" AND status IN (1) ORDER BY created_timestamp ASC

table: records

SELECT * FROM `records` WHERE user_id = "102968676886378479010" AND date = "2020-09-24"
SELECT date, SUM(spend_time) as spend_time FROM `records` WHERE user_id = "102968676886378479010" AND (date BETWEEN "2020-09-17" AND "2020-09-24") GROUP BY `date` ORDER BY date ASC
SELECT * FROM `records` WHERE user_id = "102968676886378479010" AND (date BETWEEN "2020-09-17" AND "2020-09-24")

來找共同的條件~

tasks

這兩個欄位出現的頻率最高
user_id & parent_id
直接來做一個複合式的索引
搜尋的欄位出現user_id、user_id AND parent_id,就可以吃到這索引
PS: user_id一定要排在前面

CREATE INDEX userid_parentid
ON `tasks` (`user_id`, `parent_id`);

records

user_id & date
一樣來做複合式的索引

CREATE INDEX userid_date
ON `records` (`user_id`, `date`);

今天先這樣謝謝大家~


上一篇
Day16 任務記錄API
下一篇
Day 18 零碎的小API
系列文
Golang & Vue.js 30天從0打造服務30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言